'/
' GUI Library
' Written by Anton Berlin, 2010.
' 
' =========================================================================
' 
' This program is free software; you can redistribute it and/or modify
' it under the terms of the GNU Lesser General Public License as published
' by the Free Software Foundation; either version 3 of the License.
' 
' This program is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY; without even the implied warranty of
' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
' GNU General Public License for more details.
' 
' You should have received a copy of the GNU Lesser General Public License
' along with this program; if not, write to the Free Software
' Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
'/

superstrict

import "GUI_Gadget.bmx"
import "GUI_Event.bmx"
import "GUI_Def.bmx"

import "../../framework/keycodes/keycodes.bmx"
import "../strutil/strutil.bmx"

type GUI_Form extends GUI_Gadget

	global CURSOR_FONT:TImageFont;
	
	'// -------------------------------------------------------------------------------------------------------------
	'// Input modes.
	'// -------------------------------------------------------------------------------------------------------------
	global WRITABLE_INPUT:short = 0;
	global NUMERICAL_INPUT:short = 1;
	
	'// -------------------------------------------------------------------------------------------------------------
	'// Update this gadget.
	'// -------------------------------------------------------------------------------------------------------------
	method update(currentKeyStroke:int)
	
		if (not m_selected or not m_active) ..
			return;
		
		'// Writable key?
		local key:int;
		select (m_inputMode)
		
			case WRITABLE_INPUT
				key = keycodes.isWritableKey(currentKeyStroke, false);
			case NUMERICAL_INPUT
				key = keycodes.isWritableKey(currentKeyStroke, true);
		
		end select
		if (key) ..
			m_input :+ chr(key);
		
		local text:string;
		
		if (m_password) ..
			text = strutil.repeatstr("*", m_input.length); ..
		else ..
			text = m_input;
		
		'// Functional key?
		local funcKey:int = currentKeyStroke;
		if (funcKey = KEY_SPACE) then
		
			m_input :+ " ";
		
		end if
		if (funcKey = KEY_BACKSPACE) then
		
			m_input = m_input[..m_input.length - 1];
		
		end if
		if (funcKey = KEY_ENTER) then
		
			if (m_methodHook) then
			
				execute();
			
				if (m_whipeInputOnExec) ..
					m_input = null;
			
			end if
		
		end if
	
	end method
	
	'// -------------------------------------------------------------------------------------------------------------
	'// Execute the action event linked with this gadget.
	'// -------------------------------------------------------------------------------------------------------------
	method execute()
	
		m_event = GUI_Event.create(GUI_Event.EVENT_INVOKE_METHOD, m_methodHook, m_hookedObject);
	
	end method
	
	'// -------------------------------------------------------------------------------------------------------------
	'// Draw this gadget.
	'// -------------------------------------------------------------------------------------------------------------
	method draw()
	
		if (not m_visible) ..
			return;
		
		'// Draw the design of the gadget.
		design();
	
	end method
	
	'// -------------------------------------------------------------------------------------------------------------
	'// Draw the design of this gadget.
	'// -------------------------------------------------------------------------------------------------------------
	method design()
	
		'// Prepare colors.
		local color1R:int;
		local color1G:int;
		local color1B:int;
		
		local color2R:int;
		local color2G:int;
		local color2B:int;
		
		local oldPrimitiveR:short = m_primitiveR;
		local oldPrimitiveG:short = m_primitiveG;
		local oldPrimitiveB:short = m_primitiveB;
		
		if (not m_active) then
		
			m_primitiveR :* 0.75;
			m_primitiveG :* 0.75;
			m_primitiveB :* 0.75;
		
		end if
		
		'// Setup the default drawing settings.
		drawutil.setColorInit(m_primitiveR, m_primitiveG, m_primitiveB);
		drawutil.setAlphaInit(m_transparency);
		
		'// Draw the primitive of the gadget.
		drawRect(m_posX, m_posY, m_width, m_height);
		
		'// Draw the borders and input text.
		drawBorders();
		drawInput();
		
		'// Reset drawing settings.
		drawutil.resetColor();
		drawutil.resetAlpha();
		
		if (not m_active) then
		
			m_primitiveR = oldPrimitiveR;
			m_primitiveG = oldPrimitiveG;
			m_primitiveB = oldPrimitiveB;
		
		end if
	
	end method
	
	'// -------------------------------------------------------------------------------------------------------------
	'// Draw the borders.
	'// -------------------------------------------------------------------------------------------------------------
	method drawBorders()
	
		setColor(m_primitiveR * 0.5, m_primitiveG * 0.5, m_primitiveB * 0.5);
		drawLine(m_posX, m_posY, m_posX + m_width, m_posY, false);
		drawLine(m_posX, m_posY, m_posX, m_posY + m_height, false);
		setColor(m_primitiveR * 1.5, m_primitiveG * 1.5, m_primitiveB * 1.5);
		drawLine(m_posX, m_posY + m_height, m_posX + m_width, m_posY + m_height, false);
		drawLine(m_posX + m_width, m_posY, m_posX + m_width, m_posY + m_height, false);
	
	end method
	
	'// -------------------------------------------------------------------------------------------------------------
	'// Draw the input text.
	'// -------------------------------------------------------------------------------------------------------------
	method drawInput()
	
		local text:string;
		
		if (m_password) ..
			text = strutil.repeatstr("*", m_input.length); ..
		else ..
			text = m_input;
		
		setImageFont(m_font);
		
		local offset:int = m_resX * 0.005;
		local x:int = m_posX + offset;
		local y:int = m_posY + m_height / 2 - textHeight(text) / 2 - 1;
		
		if (text) then
		
			'// Trim visible input.
			local formWidth:int = m_width - offset * 2 - textWidth("W");
			local tempText:string = text;
			
			for local index:int = tempText.length - 1 to 0 step -1
			
				tempText = text[index..text.length];
				
				if (textWidth(tempText) >= formWidth) ..
					exit;
			
			next
			
			text = tempText;
			
			'// Shadow.
			if (m_useShadows) then
			
				setAlpha(m_transparency * 0.5);
				setColor(0, 0, 0);
				drawText(text, x + 3, y + 3);
			
			end if
			
			if (m_useBorders) then
			
				'// Upper border.
				setAlpha(m_transparency * 1.0);
				setColor(m_textColorR * 0.1, m_textColorG * 0.1, m_textColorB * 0.1)
				drawText(text, x, y);
				setColor(m_textColorR * 0.1, m_textColorG * 0.1, m_textColorB * 0.1)
				drawText(text, x, y + 1);
				setColor(m_textColorR * 0.1, m_textColorG * 0.1, m_textColorB * 0.1)
				drawText(text, x + 1, y);
				
				'// Lower border.
				setColor(m_textColorR * 0.1, m_textColorG * 0.1, m_textColorB * 0.1)
				drawText(text, x + 2, y + 2);
			
			end if
			
			'// Main text.
			setColor(m_textColorR, m_textColorG, m_textColorB);
			drawText(text, x + 1, y + 1);
		
		end if
		
		'// Draw marker cursor.
		if (m_selected) then
		
			local width:int = textWidth(text);
			
			if (not CURSOR_FONT) ..
				CURSOR_FONT = loadImageFont("Data/Fonts/Arial.ttf", textHeight("|")*0.8)
			
			setImageFont(CURSOR_FONT);
			setAlpha(m_transparency * 1.0);
			setColor(m_textColorR * 0.1, m_textColorG * 0.1, m_textColorB * 0.1)
			drawText("|", x + width + 1, y);
			drawText("|", x + width + 2, y);
			setColor(m_textColorR * 0.1, m_textColorG * 0.1, m_textColorB * 0.1)
			drawText("|", x + width + 1, y + 1);
			drawText("|", x + width + 2, y + 1);
			setColor(m_textColorR * 0.1, m_textColorG * 0.1, m_textColorB * 0.1)
			drawText("|", x + width + 2, y);
			drawText("|", x + width + 3, y);
			setColor(m_textColorR * 0.1, m_textColorG * 0.1, m_textColorB * 0.1)
			drawText("|", x + width + 3, y + 2);
			drawText("|", x + width + 4, y + 2);
			setColor(m_textColorR, m_textColorG, m_textColorB);
			drawText("|", x + width + 2, y + 1);
			drawText("|", x + width + 3, y + 1);
		
		end if
	
	end method
	
	'// -------------------------------------------------------------------------------------------------------------
	'// Set what input we are going to allow.
	'// -------------------------------------------------------------------------------------------------------------
	method setInputMode(inputMode:short)
	
		m_inputMode = inputMode;
	
	end method
	
	'// -------------------------------------------------------------------------------------------------------------
	'// Set the color of the form input text.
	'// -------------------------------------------------------------------------------------------------------------
	method setTextColor(r:byte, g:byte, b:byte)
	
		m_textColorR = r;
		m_textColorG = g;
		m_textColorB = b;
	
	end method
	
	'// -------------------------------------------------------------------------------------------------------------
	'// Set the font of the form input text.
	'// -------------------------------------------------------------------------------------------------------------
	method setFont(font:TImageFont)
	
		m_font = font;
	
	end method
	
	'// -------------------------------------------------------------------------------------------------------------
	'// Set whether or not to use shadows on the input text.
	'// -------------------------------------------------------------------------------------------------------------
	method setTextShadowUsage(value:byte)
	
		m_useShadows = value;
	
	end method
	
	'// -------------------------------------------------------------------------------------------------------------
	'// Set whether or not to use the password mode, turning all characters into *'s.
	'// -------------------------------------------------------------------------------------------------------------
	method setPaswordMode(value:byte)
	
		m_password = value;
	
	end method
	
	'// -------------------------------------------------------------------------------------------------------------
	'// Set whether or not to use borders on the input text.
	'// -------------------------------------------------------------------------------------------------------------
	method setTextBorderUsage(value:byte)
	
		m_useBorders = value;
	
	end method
	
	'// -------------------------------------------------------------------------------------------------------------
	'// The font to use on the form input text.
	'// -------------------------------------------------------------------------------------------------------------
	field m_font:TImageFont;
	
	'// -------------------------------------------------------------------------------------------------------------
	'// Form input text color.
	'// -------------------------------------------------------------------------------------------------------------
	field m_textColorR:byte;
	field m_textColorG:byte;
	field m_textColorB:byte;
	
	'// -------------------------------------------------------------------------------------------------------------
	'// Flag that determines which input mode to use.
	'// -------------------------------------------------------------------------------------------------------------
	field m_inputMode:short = WRITABLE_INPUT;
	
	'// -------------------------------------------------------------------------------------------------------------
	'// Flag that determines whether or not to use shadows on the input text.
	'// -------------------------------------------------------------------------------------------------------------
	field m_useShadows:byte = false;
	
	'// -------------------------------------------------------------------------------------------------------------
	'// Flag that determines whether or not to use borders on the input text.
	'// -------------------------------------------------------------------------------------------------------------
	field m_useBorders:byte = false;
	
	'// -------------------------------------------------------------------------------------------------------------
	'// True if we should print * instead of characters, in the form.
	'// -------------------------------------------------------------------------------------------------------------
	field m_password:byte = false;
	
	'// -------------------------------------------------------------------------------------------------------------
	'// True if we should whipe the input variable after executing the action event this gadget is linked to.
	'// -------------------------------------------------------------------------------------------------------------
	field m_whipeInputOnExec:byte = true;
	
	'// -------------------------------------------------------------------------------------------------------------
	'// True if this form is currently selected.
	'// -------------------------------------------------------------------------------------------------------------
	field m_selected:byte = false;

end type

